using ObjFileLoader.Common;
using ObjFileLoader.Data;
using ObjFileLoader.Data.DataStore;
using System;
using System.Collections.Generic;
using System.IO;

namespace ObjFileLoader.Loaders
{
	public class MaterialLibraryLoader : LoaderBase, IMaterialLibraryLoader
	{
		private readonly IMaterialLibrary _materialLibrary;

		private Material _currentMaterial;

		private readonly Dictionary<string, Action<string>> _parseActionDictionary = new Dictionary<string, Action<string>>();

		private readonly List<string> _unrecognizedLines = new List<string>();

		private Material CurrentMaterial => _currentMaterial;

		public MaterialLibraryLoader(IMaterialLibrary materialLibrary)
		{
			_materialLibrary = materialLibrary;
			AddParseAction("newmtl", PushMaterial);
			AddParseAction("Ka", delegate(string d)
			{
				CurrentMaterial.AmbientColor = ParseVec3(d);
			});
			AddParseAction("Kd", delegate(string d)
			{
				CurrentMaterial.DiffuseColor = ParseVec3(d);
			});
			AddParseAction("Ks", delegate(string d)
			{
				CurrentMaterial.SpecularColor = ParseVec3(d);
			});
			AddParseAction("Ns", delegate(string d)
			{
				CurrentMaterial.SpecularCoefficient = d.ParseInvariantFloat();
			});
			AddParseAction("d", delegate(string d)
			{
				CurrentMaterial.Transparency = d.ParseInvariantFloat();
			});
			AddParseAction("Tr", delegate(string d)
			{
				CurrentMaterial.Transparency = d.ParseInvariantFloat();
			});
			AddParseAction("illum", delegate(string i)
			{
				CurrentMaterial.IlluminationModel = i.ParseInvariantInt();
			});
			AddParseAction("map_Ka", delegate(string m)
			{
				CurrentMaterial.AmbientTextureMap = m;
			});
			AddParseAction("map_Kd", delegate(string m)
			{
				CurrentMaterial.DiffuseTextureMap = m;
			});
			AddParseAction("map_Ks", delegate(string m)
			{
				CurrentMaterial.SpecularTextureMap = m;
			});
			AddParseAction("map_Ns", delegate(string m)
			{
				CurrentMaterial.SpecularHighlightTextureMap = m;
			});
			AddParseAction("map_d", delegate(string m)
			{
				CurrentMaterial.AlphaTextureMap = m;
			});
			AddParseAction("map_bump", delegate(string m)
			{
				CurrentMaterial.BumpMap = m;
			});
			AddParseAction("bump", delegate(string m)
			{
				CurrentMaterial.BumpMap = m;
			});
			AddParseAction("disp", delegate(string m)
			{
				CurrentMaterial.DisplacementMap = m;
			});
			AddParseAction("decal", delegate(string m)
			{
				CurrentMaterial.StencilDecalMap = m;
			});
		}

		private void AddParseAction(string key, Action<string> action)
		{
			_parseActionDictionary.Add(key.ToLowerInvariant(), action);
		}

		protected override void ParseLine(string keyword, string data)
		{
			Action<string> keywordAction = GetKeywordAction(keyword);
			if (keywordAction == null)
			{
				_unrecognizedLines.Add(keyword + " " + data);
			}
			else
			{
				keywordAction(data);
			}
		}

		private Action<string> GetKeywordAction(string keyword)
		{
			_parseActionDictionary.TryGetValue(keyword.ToLowerInvariant(), out Action<string> value);
			return value;
		}

		private void PushMaterial(string materialName)
		{
			_currentMaterial = new Material(materialName);
			_materialLibrary.Push(_currentMaterial);
		}

		private Vec3 ParseVec3(string data)
		{
			string[] array = data.Split(new char[1]
			{
				' '
			});
			float x = array[0].ParseInvariantFloat();
			float y = array[1].ParseInvariantFloat();
			float z = array[2].ParseInvariantFloat();
			return new Vec3(x, y, z);
		}

		public void Load(Stream lineStream)
		{
			StartLoad(lineStream);
		}
	}
}
